import mqtt from "mqtt"
export default {
    cb: {},
    leave: false,
    timeout: {
        obj: undefined,
        wait: 20000,
        topic: undefined,
        message: undefined,
    },
    host: undefined,
    options: {
        clean: true, // 保留会话
        connectTimeout: 4000, // 超时时间
        reconnectPeriod: 4000, // 重连时间间隔

        // 认证信息
        clientId: undefined,
        username: undefined,
        password: undefined,
    },
    subscribeCallback: {},
    client: {
        connected: false,
    },
    connect(subscribeMap) {
        if (!this.host) return
        if (!subscribeMap) return
        if (this.client.connected) {
            return
        }

        try {
            this.client = mqtt.connect(this.host, this.options)
        } catch (error) {
            // console.log("mqtt.connect error", error)
        }
        var reconnectII = 0
        var closeII = 0
        var retryTimesTotal = 10
        this.client.on("connect", () => {
            // console.log("Connection succeeded!")
            for (let topic in subscribeMap) {
                this.subscribe(topic, subscribeMap[topic])
            }
            reconnectII = 0
            closeII = 0
            const cbString = "connect"
            if (Object.prototype.hasOwnProperty.call(this.cb, cbString)) {
                try {
                    this.cb[cbString]()
                } catch (e) {
                    // console.log(e)
                }
            }

            if (this.timeout.message && this.timeout.topic) {
                this.clean()
                this.timeout.obj = setInterval(() => {
                    if (this.leave) {
                        this.clean()
                        return
                    }
                    if (!this.client.connected) {
                        return
                    }
                    this.publish(this.timeout.topic, this.timeout.message)
                }, this.timeout.wait)
            }
        })
        this.client.on("error", (error) => {
            // console.log("error", error)
            this.clean()
            const cbString = "error"
            if (Object.prototype.hasOwnProperty.call(this.cb, cbString)) {
                try {
                    this.cb[cbString]()
                } catch (e) {
                    // console.log(e)
                }
            }
            // console.log("Connection failed", error)
        })
        this.client.on("message", (topic, message) => {
            // console.log(`${message}`)
            if (Object.prototype.hasOwnProperty.call(this.subscribeCallback, topic)) {
                try {
                    this.subscribeCallback[topic](`${topic}`, `${message}`)
                } catch (e) {
                    // console.log(e)
                }
            }
        })
        this.client.on("close", () => {
            // console.log(`close`, closeII++)
            this.unSubscribe()
            if (retryTimesTotal <= closeII) {
                const cbString = "close"
                if (Object.prototype.hasOwnProperty.call(this.cb, cbString)) {
                    try {
                        this.cb[cbString]()
                    } catch (e) {
                        // console.log(e)
                    }
                }
            }
        })
        this.client.on("reconnect", (error) => {
            // console.log(`reconnect`, error, reconnectII++)
        })
    },
    subscribe(topic, cb) {
        let qos = 0
        this.subscribeCallback[topic] = cb
        this.client.subscribe(topic, qos, (error, res) => {
            if (error) {
                // console.log("Subscribe to topics error", error)
                return
            }
            // console.log("Subscribe to topics ", res)
        })
    },
    unSubscribe() {
        this.subscribeCallback = {}
    },
    publish(topic, payload) {
        let qos = 0
        this.client.publish(topic, payload, qos, (error) => {
            if (error) {
                // console.log("Publish error", error)
                return
            }
        })
    },
    clean() {
        clearInterval(this.timeout.obj)
    },
    close() {
        this.clean()
        try {
            this.client.end()
            this.client = {
                    connected: false,
                }
                // console.log("Successfully disconnected!")
        } catch (error) {
            // console.log("Disconnect failed", error.toString())
        }
    },
}